package com.xx.baogao.dame;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import org.apache.poi.util.Units;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;

public class WordTemplateFiller {

    public static void main(String[] args) {
        String templatePath = "C:\\Users\\admin\\Desktop\\模板.docx";
        String outputPath = "E:\\word\\填充后的报告.docx";

        try {
            // 读取模板文件
            FileInputStream fis = new FileInputStream(templatePath);
            XWPFDocument doc = new XWPFDocument(fis);

            // 准备填充数据
            Map<String, String> data = prepareFakeData();
            List<Map<String, String>> instrumentData = prepareInstrumentData();
            List<DetectionProject> detectionData = prepareDetectionData();

            // 准备图片路径
            Map<String, String> imagePaths = new HashMap<>();
            imagePaths.put("${image1}", "E:\\word\\sample1.jpg");
            imagePaths.put("${image2}", "E:\\word\\sample2.jpg");

            // 替换文档中的变量
            replaceVariables(doc, data);

            // 替换仪器表格中的多行数据
            replaceInstrumentTable(doc, instrumentData);

            // 替换检测方案表格数据
            replaceDetectionTable(doc, detectionData);

            // 替换检测结果表格
            replaceResultTables(doc, data);

            // 替换图片
            replaceImages(doc, imagePaths);

            // 保存填充后的文档
            FileOutputStream fos = new FileOutputStream(outputPath);
            doc.write(fos);
            fos.close();
            fis.close();

            System.out.println("文档填充完成，已保存到: " + outputPath);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static Map<String, String> prepareFakeData() {
        Map<String, String> data = new HashMap<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");

        // 报告基本信息
        data.put("reportNo", "JCYW202410050296");
        data.put("projectName", "污水检测项目");
        data.put("clientName", "山东某科技有限公司");
        data.put("testPoint", "常规检测");
        data.put("reportDate", sdf.format(new Date()));
        data.put("address", "山东省济南市高新区舜华路2000号");
        data.put("code", "250101");
        data.put("phone", "0531-88889999");
        data.put("telphone", "0531-88889998");
        data.put("email", "service@sdtech.com");

        // 基本情况
        data.put("man", "张经理");
        data.put("type", "环境检测");
        data.put("sampleDate", sdf.format(new Date()));
        data.put("sampleMan", "李采样, 王采样");

        // 检测方案
        data.put("projectType", "水质检测");
        data.put("point", "A区采样点");
        data.put("detectProject", "pH值, COD, BOD5, 氨氮");
        data.put("count", "3次/天");
        data.put("method", "GB/T 5750.2-2006 生活饮用水标准检验方法");

        // 检测方法
        data.put("method_name", "电极法, 重铬酸钾法, 纳氏试剂分光光度法");
        data.put("method_come", "GB/T 6920-1986, GB/T 11914-1989, HJ 535-2009");
        data.put("detection_mothod", "0.1, 5, 0.025");

        // 检测结果
        data.put("detectDate", sdf.format(new Date()));
        data.put("detectResult", "7.2, 45.6, 12.3, 2.8");

        // 样品信息
        data.put("countAndContainer", "3瓶，500mL玻璃瓶");
        data.put("sampleStatus", "液态");
        data.put("sampleColor", "淡黄色");
        data.put("sampleSmell", "轻微异味");
        data.put("oil", "无");

        // 样品编号
        data.put("sampleCode", "WQ-2024-001-01, WQ-2024-001-02");
        data.put("remark", "冷藏保存");

        return data;
    }

    private static List<Map<String, String>> prepareInstrumentData() {
        List<Map<String, String>> instruments = new ArrayList<>();

        // 添加第一条仪器数据
        Map<String, String> instrument1 = new HashMap<>();
        instrument1.put("instrument", "水质多参数分析仪");
        instrument1.put("model", "Multi 3630");
        instrument1.put("serialNo", "WQ-2024-001");
        instruments.add(instrument1);

        // 添加第二条仪器数据
        Map<String, String> instrument2 = new HashMap<>();
        instrument2.put("instrument", "气相色谱仪");
        instrument2.put("model", "GC-2014");
        instrument2.put("serialNo", "GC-2023-015");
        instruments.add(instrument2);

        // 添加第三条仪器数据
        Map<String, String> instrument3 = new HashMap<>();
        instrument3.put("instrument", "原子吸收光谱仪");
        instrument3.put("model", "AA-6800");
        instrument3.put("serialNo", "AA-2024-003");
        instruments.add(instrument3);

        return instruments;
    }

    private static List<DetectionProject> prepareDetectionData() {
        List<DetectionProject> projects = new ArrayList<>();

        // 第一个项目类别 - 水质检测
        DetectionProject waterProject = new DetectionProject();
        waterProject.setProjectType("水质检测");
        List<DetectionPoint> waterPoints = new ArrayList<>();
        waterPoints.add(new DetectionPoint("A区采样点", "pH值, COD", "3次/天"));
        waterPoints.add(new DetectionPoint("A区采样点", "BOD5, 氨氮", "2次/天"));
        waterPoints.add(new DetectionPoint("B区采样点", "重金属含量", "1次/天"));
        waterProject.setPoints(waterPoints);
        projects.add(waterProject);

        // 第二个项目类别 - 空气质量检测
        DetectionProject airProject = new DetectionProject();
        airProject.setProjectType("空气质量检测");
        List<DetectionPoint> airPoints = new ArrayList<>();
        airPoints.add(new DetectionPoint("厂区东侧", "PM2.5, PM10", "每小时1次"));
        airPoints.add(new DetectionPoint("厂区西侧", "SO2, NO2", "每2小时1次"));
        airProject.setPoints(airPoints);
        projects.add(airProject);

        return projects;
    }

    private static void replaceVariables(XWPFDocument doc, Map<String, String> data) {
        // 替换段落中的变量
        for (XWPFParagraph p : doc.getParagraphs()) {
            String text = p.getText();
            if (text != null && text.contains("$")) {
                for (Map.Entry<String, String> entry : data.entrySet()) {
                    if (text.contains(entry.getKey())) {
                        text = text.replace("${" + entry.getKey() + "}", entry.getValue());
                    }
                }
                // 清除原有内容
                for (int i = p.getRuns().size() - 1; i >= 0; i--) {
                    p.removeRun(i);
                }
                // 添加新内容
                p.createRun().setText(text);
            }
        }

        // 替换表格中的变量（不包括仪器表格和检测方案表格）
        for (XWPFTable table : doc.getTables()) {
            if (!isInstrumentTable(table) && !isDetectionTable(table) && !isResultTable(table)) {
                for (XWPFTableRow row : table.getRows()) {
                    for (XWPFTableCell cell : row.getTableCells()) {
                        for (XWPFParagraph p : cell.getParagraphs()) {
                            String text = p.getText();
                            if (text != null && text.contains("$")) {
                                for (Map.Entry<String, String> entry : data.entrySet()) {
                                    if (text.contains(entry.getKey())) {
                                        text = text.replace("${" + entry.getKey() + "}", entry.getValue());
                                    }
                                }
                                // 清除原有内容
                                for (int i = p.getRuns().size() - 1; i >= 0; i--) {
                                    p.removeRun(i);
                                }
                                // 添加新内容
                                p.createRun().setText(text);
                            }
                        }
                    }
                }
            }
        }
    }

    private static void replaceInstrumentTable(XWPFDocument doc, List<Map<String, String>> instrumentData) {
        // 找到仪器表格
        for (XWPFTable table : doc.getTables()) {
            if (isInstrumentTable(table)) {
                // 保留表头行
                XWPFTableRow headerRow = table.getRow(0);

                // 清除表格中除表头外的所有行
                while (table.getRows().size() > 1) {
                    table.removeRow(1);
                }

                // 添加仪器数据行
                for (Map<String, String> instrument : instrumentData) {
                    XWPFTableRow newRow = table.createRow();

                    // 设置仪器名称
                    setCellValue(newRow, 0, instrument.get("instrument"));

                    // 设置仪器型号
                    setCellValue(newRow, 1, instrument.get("model"));

                    // 设置仪器编号
                    setCellValue(newRow, 2, instrument.get("serialNo"));
                }

                break;
            }
        }
    }

    private static void replaceDetectionTable(XWPFDocument doc, List<DetectionProject> projects) {
        for (XWPFTable table : doc.getTables()) {
            if (isDetectionTable(table)) {
                // 保留表头行
                XWPFTableRow headerRow = table.getRow(0);

                // 清除表格中除表头外的所有行
                while (table.getRows().size() > 1) {
                    table.removeRow(1);
                }

                // 添加项目数据行并记录合并范围
                Map<String, List<Integer>> mergeRanges = new HashMap<>();
                int currentRow = 1; // 从第二行开始（表头是第一行）

                for (DetectionProject project : projects) {
                    int startRow = currentRow;
                    boolean isFirstRow = true;

                    for (DetectionPoint point : project.getPoints()) {
                        XWPFTableRow newRow = table.createRow();

                        // 如果是该项目的第一行，显示项目类别并设置居中
                        if (isFirstRow) {
                            XWPFTableCell typeCell = getOrCreateCell(newRow, 0);
                            setCellValueInCell(typeCell, project.getProjectType());
                            setCellCenterAlignment(typeCell);
                            isFirstRow = false;
                        } else {
                            setCellValueInCell(getOrCreateCell(newRow, 0), "");
                        }

                        // 设置其他列数据
                        setCellValueInCell(getOrCreateCell(newRow, 1), point.getPointName());
                        setCellValueInCell(getOrCreateCell(newRow, 2), point.getDetectProject());
                        setCellValueInCell(getOrCreateCell(newRow, 3), point.getCount());

                        currentRow++;
                    }

                    // 记录需要合并的行范围（只有多于1行时才需要合并）
                    if (currentRow - startRow > 1) {
                        mergeRanges.put(project.getProjectType(), Arrays.asList(startRow, currentRow - 1));
                    }
                }

                // 合并相同项目类别的单元格
                for (List<Integer> range : mergeRanges.values()) {
                    mergeCellsVertically(table, 0, range.get(0), range.get(1));
                }

                break;
            }
        }
    }

    private static void replaceResultTables(XWPFDocument doc, Map<String, String> data) {
        for (XWPFTable table : doc.getTables()) {
            if (isResultTable(table)) {
                // 获取表格中的变量并替换
                for (XWPFTableRow row : table.getRows()) {
                    for (XWPFTableCell cell : row.getTableCells()) {
                        for (XWPFParagraph p : cell.getParagraphs()) {
                            String text = p.getText();
                            if (text != null && text.contains("$")) {
                                for (Map.Entry<String, String> entry : data.entrySet()) {
                                    if (text.contains(entry.getKey())) {
                                        text = text.replace("${" + entry.getKey() + "}", entry.getValue());
                                    }
                                }
                                // 清除原有内容
                                for (int i = p.getRuns().size() - 1; i >= 0; i--) {
                                    p.removeRun(i);
                                }
                                // 添加新内容
                                p.createRun().setText(text);
                            }
                        }
                    }
                }
            }
        }
    }

    private static void replaceImages(XWPFDocument doc, Map<String, String> imagePaths) throws IOException {
        // 获取文档中所有段落
        for (XWPFParagraph p : doc.getParagraphs()) {
            for (XWPFRun run : p.getRuns()) {
                String text = run.getText(0);
                if (text != null && text.contains("${image")) {
                    // 提取图片变量名
                    String imageVar = text.substring(text.indexOf("${"), text.indexOf("}") + 1);
                    String imagePath = imagePaths.get(imageVar);

                    if (imagePath != null) {
                        // 清除原有文本
                        run.setText("", 0);

                        // 添加图片
                        try (FileInputStream is = new FileInputStream(imagePath)) {
                            try {
                                run.addPicture(is,
                                        XWPFDocument.PICTURE_TYPE_JPEG,
                                        imagePath,
                                        Units.toEMU(200),  // 宽度
                                        Units.toEMU(150)); // 高度
                            } catch (InvalidFormatException e) {
                                System.err.println("图片格式无效: " + imagePath);
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }
        }

        // 处理表格中的图片
        for (XWPFTable table : doc.getTables()) {
            for (XWPFTableRow row : table.getRows()) {
                for (XWPFTableCell cell : row.getTableCells()) {
                    for (XWPFParagraph p : cell.getParagraphs()) {
                        for (XWPFRun run : p.getRuns()) {
                            String text = run.getText(0);
                            if (text != null && text.contains("${image")) {
                                String imageVar = text.substring(text.indexOf("${"), text.indexOf("}") + 1);
                                String imagePath = imagePaths.get(imageVar);

                                if (imagePath != null) {
                                    run.setText("", 0);
                                    try (FileInputStream is = new FileInputStream(imagePath)) {
                                        try {
                                            run.addPicture(is,
                                                    XWPFDocument.PICTURE_TYPE_JPEG,
                                                    imagePath,
                                                    Units.toEMU(200),
                                                    Units.toEMU(150));
                                        } catch (InvalidFormatException e) {
                                            System.err.println("图片格式无效: " + imagePath);
                                            e.printStackTrace();
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    private static boolean isInstrumentTable(XWPFTable table) {
        // 检查表格是否是仪器表格（根据第一行内容判断）
        if (table.getRows().size() > 0) {
            XWPFTableRow firstRow = table.getRow(0);
            if (firstRow.getTableCells().size() >= 3) {
                String firstCellText = firstRow.getCell(0).getText();
                return firstCellText != null && firstCellText.contains("仪器名称");
            }
        }
        return false;
    }

    private static boolean isDetectionTable(XWPFTable table) {
        if (table.getRows().size() > 0) {
            XWPFTableRow firstRow = table.getRow(0);
            if (firstRow.getTableCells().size() >= 4) {
                String firstCellText = firstRow.getCell(0).getText();
                return firstCellText != null && firstCellText.contains("项目类别");
            }
        }
        return false;
    }

    private static boolean isResultTable(XWPFTable table) {
        if (table.getRows().size() > 0) {
            XWPFTableRow firstRow = table.getRow(0);
            if (firstRow.getTableCells().size() >= 4) {
                String firstCellText = firstRow.getCell(0).getText();
                return firstCellText != null && (firstCellText.contains("检测日期") || firstCellText.contains("检测点位"));
            }
        }
        return false;
    }

    private static void setCellValue(XWPFTableRow row, int cellIndex, String value) {
        XWPFTableCell cell = row.getCell(cellIndex);
        if (cell == null) {
            cell = row.createCell();
        }

        // 清除单元格原有内容
        for (int i = cell.getParagraphs().size() - 1; i >= 0; i--) {
            cell.removeParagraph(i);
        }

        // 添加新内容
        XWPFParagraph p = cell.addParagraph();
        XWPFRun r = p.createRun();
        r.setText(value);
    }

    private static void mergeCellsVertically(XWPFTable table, int col, int startRow, int endRow) {
        for (int rowIndex = startRow; rowIndex <= endRow; rowIndex++) {
            XWPFTableCell cell = table.getRow(rowIndex).getCell(col);

            // 获取或创建单元格属性
            if (cell.getCTTc().getTcPr() == null) {
                cell.getCTTc().addNewTcPr();
            }

            // 使用正确的合并常量
            if (rowIndex == startRow) {
                // 合并起始单元格
                cell.getCTTc().getTcPr().addNewVMerge().setVal(STMerge.RESTART);
            } else {
                // 合并延续单元格
                cell.getCTTc().getTcPr().addNewVMerge().setVal(STMerge.CONTINUE);
            }
        }
    }

    private static void setCellCenterAlignment(XWPFTableCell cell) {
        if (cell == null) return;

        // 水平居中
        for (XWPFParagraph p : cell.getParagraphs()) {
            p.setAlignment(ParagraphAlignment.CENTER);
        }

        // 垂直居中
        cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
    }

    private static void setCellValueInCell(XWPFTableCell cell, String value) {
        if (cell == null) return;

        // 清除单元格原有内容
        for (int i = cell.getParagraphs().size() - 1; i >= 0; i--) {
            cell.removeParagraph(i);
        }

        // 添加新内容
        XWPFParagraph p = cell.addParagraph();
        XWPFRun r = p.createRun();
        r.setText(value == null ? "" : value);
    }

    private static XWPFTableCell getOrCreateCell(XWPFTableRow row, int cellIndex) {
        XWPFTableCell cell = row.getCell(cellIndex);
        if (cell == null) {
            cell = row.createCell();
        }
        return cell;
    }
}

class DetectionProject {
    private String projectType;
    private List<DetectionPoint> points;

    public DetectionProject() {}

    public String getProjectType() {
        return projectType;
    }

    public void setProjectType(String projectType) {
        this.projectType = projectType;
    }

    public List<DetectionPoint> getPoints() {
        return points;
    }

    public void setPoints(List<DetectionPoint> points) {
        this.points = points;
    }
}

class DetectionPoint {
    private String pointName;
    private String detectProject;
    private String count;

    public DetectionPoint(String pointName, String detectProject, String count) {
        this.pointName = pointName;
        this.detectProject = detectProject;
        this.count = count;
    }

    public String getPointName() {
        return pointName;
    }

    public String getDetectProject() {
        return detectProject;
    }

    public String getCount() {
        return count;
    }
}